﻿using System;
using System.Collections.Generic;
using Autofac;
using MdcService.Configuration;
using MdcService.DataAccess;
using MdcService.External;
using MdcService.Log;
using MdcService.Service;
using MdcService.Structure;


namespace MdcService
{
	public class Mdc : IService
	{
	    private IContainer Container { get; }
        private readonly CollectingService _collectService;
		private readonly RecordingService _recordService;
	    private readonly RestService _restService;
	    private readonly ILogging _logging;
	    private readonly ProcedureService _procedureService;

	    public readonly ConfigurationService ConfigurationService;
        public readonly RunningContext RunningContext;
	    public readonly HistoryDbService HistoryDbService;
	    public readonly RealtimeDbService RealtimeDbService;

	    public event EventHandler<EventArgs> Started;
	    public event EventHandler<EventArgs> Stopped;

	    public Configuration.Configuration Configuration => ConfigurationService.Configuration;
	    public IList<MachineDefinition> MachineDefinitions => ConfigurationService.MachineDefinitions;

        public Mdc()
		{
            var builder = new ContainerBuilder();
		    builder.RegisterType<RunningContext>().AsSelf().SingleInstance();
		    builder.RegisterType<IniConfigurationManager>().As<IConfigurationManager<Configuration.Configuration>>().SingleInstance();
		    builder.RegisterType<IniMachinesManager>().As<IConfigurationManager<IList<MachineDefinition>>>().SingleInstance();
		    builder.RegisterType<ConfigurationService>().AsSelf().SingleInstance();
            builder.RegisterType<NullExternalService>().As<IExternalService>().SingleInstance();
		    builder.RegisterType<Log4NetLogger>().As<ILogging>().SingleInstance();
            builder.RegisterType<MemoryDataAccess>().As<IRealTimeDataAccess<MachineValue>>().SingleInstance();
            builder.RegisterType<RealtimeDbService>().AsSelf().SingleInstance();
            builder.RegisterType<MemoryDataAccess>().As<IHistoryDataAccess<MachineValue>>().SingleInstance();
            builder.RegisterType<HistoryDbService>().AsSelf().SingleInstance();
            builder.RegisterType<RecordingService>().AsSelf().SingleInstance();
            builder.RegisterType<CollectingService>().AsSelf().SingleInstance();
            builder.RegisterType<RestService>().AsSelf().SingleInstance();
		    builder.RegisterType<ProcedureService>().AsSelf().SingleInstance();

            Container = builder.Build();

		    ConfigurationService = Container.Resolve<ConfigurationService>();
		    _recordService = Container.Resolve<RecordingService>();
		    _collectService = Container.Resolve<CollectingService>();
		    _restService = Container.Resolve<RestService>();
		    RunningContext = Container.Resolve<RunningContext>();
		    HistoryDbService = Container.Resolve<HistoryDbService>();
		    RealtimeDbService = Container.Resolve<RealtimeDbService>();
		    _logging = Container.Resolve<ILogging>();
		    _procedureService = Container.Resolve<ProcedureService>();

		    _procedureService
		        .QueueStart(ConfigurationService)
		        .QueueStart(RealtimeDbService)
		        .QueueStart(HistoryDbService)
		        .QueueStart(_collectService)
		        .QueueStart(_recordService)
		        .QueueStart(_restService);

		    _procedureService
		        .QueueStop(_restService)
		        .QueueStop(_collectService)
		        .QueueStop(_recordService)
		        .QueueStop(RealtimeDbService)
		        .QueueStop(HistoryDbService)
		        .QueueStop(ConfigurationService);

		    _procedureService.Started += (s, e) => Started?.Invoke(this, null);
		    _procedureService.Stopped += (s, e) => Stopped?.Invoke(this, null);
		}

        public void Start() => _procedureService.Start();

		public void Stop()=> _procedureService.Stop();

	}
}
